/* 
 * Copyright (C) 2012 UTSChedule
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package utsc.apps.utschedule.util.database;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.nio.channels.FileChannel;
import java.text.SimpleDateFormat;
import java.util.Date;
import utsc.apps.utschedule.R;
import utsc.apps.utschedule.UTSCheduleApp;
import utsc.apps.utschedule.classes.Assignment;
import utsc.apps.utschedule.classes.Course;
import utsc.apps.utschedule.classes.Exam;
import utsc.apps.utschedule.classes.Timetable;
import android.app.SearchManager;
import android.content.Context;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.os.Environment;
import android.util.Log;
import android.widget.Toast;

import com.j256.ormlite.android.apptools.OrmLiteSqliteOpenHelper;
import com.j256.ormlite.dao.Dao;
import com.j256.ormlite.support.ConnectionSource;
import com.j256.ormlite.table.TableUtils;

/**
 * A utility helper class for creating all the tables and connecting the database. 
 *
 */
public class DatabaseHelper extends OrmLiteSqliteOpenHelper {

	
	private static final String DB_NAME="utschedule.db";
	private static final int DB_VERSION=2;
	private Dao<Timetable, Integer> _timetableDao=null;
	private Dao<Course, Integer> _courseDao=null;
	private Dao<Assignment, Integer> _assignmentDao=null;
	private Dao<Exam, Integer> _examDao=null;
	
	//construct the create statement of the search suggestion table
	//use the built-in full text search feature
	private static final String FTS_SUGGESTION_TABLE_CREATE = "CREATE VIRTUAL TABLE FTSsuggestion USING fts3 ("
			+ SearchManager.SUGGEST_COLUMN_TEXT_1+ ", "
			+ SearchManager.SUGGEST_COLUMN_TEXT_2+ ", "
			+SearchManager.SUGGEST_COLUMN_INTENT_ACTION+", "
			+SearchManager.SUGGEST_COLUMN_INTENT_DATA+ ", "
			+SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID+", timetable_id, type);";
	
	
	public DatabaseHelper(Context context) {
		super(context, DB_NAME, null, DB_VERSION,R.raw.ormlite_config);
	}
	
	@Override
	public void onCreate(SQLiteDatabase db, ConnectionSource connectionSource) {
		try {
			//use ORMLite to create the tables for us
			TableUtils.createTable(connectionSource, Timetable.class);
            TableUtils.createTable(connectionSource, Course.class);
            TableUtils.createTable(connectionSource, Assignment.class);
            TableUtils.createTable(connectionSource, Exam.class);
            //here we manually create our search suggestion table
            db.execSQL(FTS_SUGGESTION_TABLE_CREATE);
            
        } catch (SQLException e) {
            Log.e(DatabaseHelper.class.getName(), "Can't create database", e);
            throw new RuntimeException(e);
        } catch (java.sql.SQLException e) {
            e.printStackTrace();
        }
	}
	@Override
	public void onUpgrade(SQLiteDatabase arg0, ConnectionSource arg1, int arg2,
			int arg3) {
	}
	
	public Dao<Timetable, Integer> get_timetableDao() {
		if (_timetableDao==null) {
            try {
                _timetableDao=getDao(Timetable.class);
                _timetableDao.setObjectCache(true);
            }catch (java.sql.SQLException e) {
                e.printStackTrace();
            }
        }
		return _timetableDao;
	}
	
	public Dao<Course, Integer> get_courseDao() {
		if (_courseDao==null) {
			try {
				_courseDao=getDao(Course.class);
				_courseDao.setObjectCache(true);
			} catch (java.sql.SQLException e) {
				e.printStackTrace();
			}
		}
		return _courseDao;
	}
	
	public Dao<Assignment, Integer> get_assignmentDao() {
		if (_assignmentDao==null) {
			try {
				_assignmentDao=getDao(Assignment.class);
				_assignmentDao.setObjectCache(true);
			} catch (java.sql.SQLException e) {
				e.printStackTrace();
			}
		}
		return _assignmentDao;
	}
	public Dao<Exam, Integer> get_examDao() {
		if (_examDao==null) {
            try {
            	_examDao=getDao(Exam.class);
            	_examDao.setObjectCache(true);
            }catch (java.sql.SQLException e) {
                e.printStackTrace();
            }
        }
		return _examDao;
	}
	
	/**
	 * A utility method to backup the whole database into the SD media storage.
	 * @param context
	 */
	public static void backupDb(Context context){
		 try {
				DatabaseManager.release();
		        File sd = Environment.getExternalStorageDirectory();
		        if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
		        	Log.d(DB_NAME, sd.canWrite()+"");
				}
		        if (sd.canWrite()) {
		        	SimpleDateFormat timestampeFormatter=new SimpleDateFormat("yyyy-MM-dd_k_mm");
		            String backupDBPath = "/UTSChedule/UTSChedule_"+timestampeFormatter.format(new Date(System.currentTimeMillis()));
		            File currentDB = context.getDatabasePath(DB_NAME);
		            File backupDB = new File(sd, backupDBPath);
		            new File(sd,"UTSChedule").mkdir();
		            if (currentDB.exists()) {
		                FileChannel src = new FileInputStream(currentDB).getChannel();
		                FileChannel dst = new FileOutputStream(backupDB).getChannel();
		                dst.transferFrom(src, 0, src.size());
		                src.close();
		                dst.close();
		                Toast.makeText(context, "Database is sucessfully backup to: "+backupDB.toString(), Toast.LENGTH_LONG).show();
		            }
		        }
		    } catch (Exception e) {
		    	e.printStackTrace();
		    }
	}
	
	/**
	 * Copies the database file at the specified location over the current
	 * internal application database.
	 * */
	public static void restoreDb(String dbPath, Context context) {

		// Close the SQLiteOpenHelper so it will commit the created empty
		// database to internal storage.
		try {
			DatabaseManager.release();
			File newDb = new File(dbPath);
			File oldDb = context.getDatabasePath(DB_NAME);
			if (newDb.exists()) {
				FileChannel fromChannel = new FileInputStream(newDb).getChannel();
				FileChannel toChannel = new FileOutputStream(oldDb).getChannel();
				fromChannel.transferTo(0, fromChannel.size(), toChannel);
				fromChannel.close();
				toChannel.close();
				Toast.makeText(context, "Database is sucessfully restored from: "+dbPath, Toast.LENGTH_LONG).show();
				// Access the copied database so SQLiteHelper will cache it and
				// mark
				// it as created.
				
				DatabaseManager.getInstance(context).refreshObjectCache();
				UTSCheduleApp app=(UTSCheduleApp) context.getApplicationContext();
				app.get_currentActiveTimetable().refreshCourseList();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
